package yxy.game.pm2.module.capturestrategicpoints;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.TypeReference;
import jodd.util.StringUtil;
import org.redisson.api.RMap;
import yxy.apple.util.ArraryMesh;
import yxy.cherry.battle.Team;
import yxy.cherry.battle.module.Position;
import yxy.cherry.battle.module.record.result.BattleResult;
import yxy.cherry.data.DataCenter;
import yxy.cherry.data.bean.clearancemonster;
import yxy.cherry.data.bean.clearancereward;
import yxy.cherry.game.base.redis.RedisManager;
import yxy.cherry.game.base.redis.RedisType;
import yxy.game.pm2.Result;
import yxy.game.pm2.bean.Currency;
import yxy.game.pm2.bean.Format;
import yxy.game.pm2.bean.Hero;
import yxy.game.pm2.message.*;
import yxy.game.pm2.module.CurrencyHandle;
import yxy.game.pm2.module.battle.*;
import yxy.game.pm2.module.hero.FormatHandle;
import yxy.game.pm2.module.hero.HeroHandle;
import yxy.game.pm2.module.niubee.NiuBeeModule;

import java.util.*;

import static yxy.cherry.data.DataCenter.getAllData;

/**
 * @author wrs
 * @descrition 斩关夺隘处理类
 * @since 2022-08-15
 */
public class CaptureStrategicPointsHandle {
    // 战斗处理===========================================================================
    private static String code() {
        return BattleType.CAPTUREPOINTS.name();
    }

    /**
     * 封装布阵信息
     *
     * @param playerCode
     * @param module
     * @param response
     * @return
     */
    public Result packFormatInfo(String playerCode, CaptureStrategicPointsModule module, CaptureStrategicPointsMessage.CaptureStrategicPointsFormatResponse.Builder response) {
        NiuBeeModule niuBeeModule = NiuBeeModule.get(playerCode);
        int progress = niuBeeModule == null ? 0 : niuBeeModule.getProgress();
        int level = niuBeeModule == null ? 0 : niuBeeModule.getLevel();

        response.setNbAct(progress);
        response.setNbLevel(level);
        FormatMessageEntry entry = getFormatInfo(playerCode, module, 0, true);
        response.addAllFormat(entry.getFormats());
        response.addAllHeros(entry.getHeros());
        return Result.Success;
    }

    /**
     * 处理阵容信息返回
     *
     * @param formatNum
     */
    public FormatMessageEntry getFormatInfo(String playerCode, CaptureStrategicPointsModule module, int formatNum, boolean isAll) {
        HashMap<String, Hero> heros = new HashMap<>();
        FormatMessageEntry entry = new FormatMessageEntry();

        int i = 0;
        for (Format format : module.getFormats()) {
            FormatMessage.Format.Builder formatBuilder = FormatMessage.Format.newBuilder();

            ArrayList<Hero> formatHeroList = new ArrayList<>();
            Hero herofu = Hero.get(playerCode, format.getFu());
            if (format.getFu() != null && herofu != null) {
                heros.put(herofu.getCode(), herofu);
                formatHeroList.add(herofu);
                formatBuilder.setFU(format.getFu());
            }

            Hero herofm = Hero.get(playerCode, format.getFm());
            if (format.getFm() != null && herofm != null) {
                heros.put(herofm.getCode(), herofm);
                formatHeroList.add(herofm);
                formatBuilder.setFM(format.getFm());
            }

            Hero herofd = Hero.get(playerCode, format.getFd());
            if (format.getFd() != null && herofd != null) {
                heros.put(herofd.getCode(), herofd);
                formatHeroList.add(herofd);
                formatBuilder.setFD(format.getFd());
            }

            Hero herobu = Hero.get(playerCode, format.getBu());
            if (format.getBu() != null && herobu != null) {
                heros.put(herobu.getCode(), herobu);
                formatHeroList.add(herobu);
                formatBuilder.setBU(format.getBu());
            }

            Hero herobm = Hero.get(playerCode, format.getBm());
            if (format.getBm() != null && herobm != null) {
                heros.put(herobm.getCode(), herobm);
                formatHeroList.add(herobm);
                formatBuilder.setBM(format.getBm());
            }

            Hero herobd = Hero.get(playerCode, format.getBd());
            if (format.getBd() != null && herobd != null) {
                heros.put(herobd.getCode(), herobd);
                formatHeroList.add(herobd);
                formatBuilder.setBD(format.getBd());
            }

            formatBuilder.setNB(format.getNb());
            entry.addFormat(formatBuilder.build());

            //从缓存获取
            long totalPower = 0;
            for (Hero hero : formatHeroList) {
                if (hero.getPower() != null) {
                    totalPower += hero.getPower();
                } else {
                    totalPower += new BattleHandle().calculatePower(playerCode, hero, format);
                }
            }

            entry.getFormatPower().add(totalPower);

            if (formatNum > 0 && ++i >= formatNum) {
                break;
            }
        }

        HeroHandle heroHandle = new HeroHandle();
        if (isAll) {
            LinkedList<HeroMessage.HeroSimple> heroSimples = new LinkedList<>();
            for (Hero hero : Hero.all(playerCode).values()) {
                heroSimples.add(heroHandle.getHeroSimple(playerCode, hero));
            }
            entry.addHero(playerCode, heroSimples);

        } else {
            LinkedList<HeroMessage.HeroSimple> heroSimples = new LinkedList<>();
            for (Hero hero : heros.values()) {
                heroSimples.add(heroHandle.getHeroSimple(playerCode, hero));
            }
            entry.addHero(playerCode, heroSimples);
        }

        return entry;
    }


    /**
     * 布阵保存
     *
     * @param playerCode
     * @param formatList
     * @return
     */
    public Result formatSet(String playerCode, List<FormatMessage.Format> formatList, CaptureStrategicPointsModule module) {

        if (formatList.size() < 3) {
            return Result.CaptureStrategicPointsFormatLess;// 参战阵容不全
        }

        Map<Integer, Hero> map = new HashMap<>();
        ArrayList<Format> formats = new ArrayList<>();


        for (FormatMessage.Format formatrequest : formatList) {
            Format format = new Format();
            Result result = checkFormat(playerCode, format, null, map, formatrequest);
            if (!result.equals(Result.Success)) {
                return result;
            }
            formats.add(format);
        }

        //保存
        module.getFormats().clear();
        module.getFormats().addAll(formats);
        module.set();
        return Result.Success;

    }


    //检查阵容
    private Result checkFormat(String playerCode, Format format, Map<String, Hero> all, Map<Integer, Hero> map, FormatMessage.Format formatrequest) {
        if (format == null) {
            return Result.DataError;
        }

        FormatHandle formatHandle = new FormatHandle();

        if (!StringUtil.isEmpty(formatrequest.getFU())) {
            format.setFu(formatrequest.getFU());
        }
        if (!StringUtil.isEmpty(formatrequest.getFM())) {
            format.setFm(formatrequest.getFM());
        }
        if (!StringUtil.isEmpty(formatrequest.getFD())) {
            format.setFd(formatrequest.getFD());
        }
        if (!StringUtil.isEmpty(formatrequest.getBU())) {
            format.setBu(formatrequest.getBU());
        }
        if (!StringUtil.isEmpty(formatrequest.getBM())) {
            format.setBm(formatrequest.getBM());
        }
        if (!StringUtil.isEmpty(formatrequest.getBD())) {
            format.setBd(formatrequest.getBD());
        }
        int nb = formatrequest.getNB();
        format.setNb(nb);

        try {
            formatHandle.checkFormat(playerCode, format.getFu(), map);
            formatHandle.checkFormat(playerCode, format.getFm(), map);
            formatHandle.checkFormat(playerCode, format.getFd(), map);
            formatHandle.checkFormat(playerCode, format.getBu(), map);
            formatHandle.checkFormat(playerCode, format.getBm(), map);
            formatHandle.checkFormat(playerCode, format.getBd(), map);
        } catch (Exception e) {
            return Result.FormatSameHero;// 不能上阵同样的武将
        }

        // 检查神器
        if (format.getNb() > 0) {
            NiuBeeModule niubeeModule = NiuBeeModule.get(playerCode);
            if (niubeeModule.getProgress() < format.getNb()) {
                return Result.FormatNiubeeError;// 神器设置错误
            }
        }

        return Result.Success;
    }

    /**
     * 获取已通关的数量
     *
     * @param module
     * @return
     */
    public int getPassCustomNum(CaptureStrategicPointsModule module) {
        int total = 0;
        HashMap<Integer, Integer> map = module.getCheckpointRecord();
        for (Integer value : map.values()) {
            total = total + value;
        }
        return total;
    }


    /**
     * 获取封装数据 OneDayMsgModule
     *
     * @param module
     * @return
     */
    public static ArrayList<CaptureStrategicPointsMessage.OneDayMsgModule.Builder> getOneDayMsgModule(CaptureStrategicPointsModule module) {
        ArrayList<CaptureStrategicPointsMessage.OneDayMsgModule.Builder> list = new ArrayList<>();
        Map<String, clearancemonster> monster = getAllData(clearancemonster.class);//怪物表
        Map<String, clearancereward> reward = getAllData(clearancereward.class);//右侧宝箱表

        HashMap<Integer, HashMap<Integer, Boolean>> map = module.getOpenCustomsMap();

        Set<Map.Entry<Integer, HashMap<Integer, Boolean>>> entries = map.entrySet();

        for (Map.Entry<Integer, HashMap<Integer, Boolean>> entry : entries) {
            Integer day = entry.getKey();
            HashMap<Integer, Boolean> value = entry.getValue();
            //todo 1.封装 OneDayMsgModule
            CaptureStrategicPointsMessage.OneDayMsgModule.Builder builder = CaptureStrategicPointsMessage.OneDayMsgModule.newBuilder();
            //todo 2.天数
            builder.setTime(day);
            //todo 3.怪物数据
            int degree = module.getDegree();//todo 动态改变怪物战力,难度等级（动态）
            for (clearancemonster clearancemonster : monster.values()) {
                if (clearancemonster.getField() == day) {
                    CaptureStrategicPointsMessage.CustomsModule.Builder CustomsModuleBuilder = CaptureStrategicPointsMessage.CustomsModule.newBuilder();
                    CustomsModuleBuilder.setStars(clearancemonster.getStars());//星星数量
                    CustomsModuleBuilder.setId(clearancemonster.getId());//关卡id
                    long totalPower = 0;//怪物们的总战力
                    ArrayList<FighterModule> fighterModule = getFighterModule(clearancemonster.getId());

                    for (int i = 0; i < clearancemonster.getHeroid().length; i++) {
                        int heroid = clearancemonster.getHeroid()[i];
                        if (heroid == -1) continue;
                        FighterModule fight = fighterModule.get(i);
                        //根据等级提升怪物难度
                        fight.setLevel(fight.getLevel() + degree * 5);
                        fight.getProperty().addPropertyDataBasicDegree(degree, 10);
                        totalPower += fight.getTotalPower() + fight.getTotalPower() * degree * 0.05;
                        //怪物信息
                        CaptureStrategicPointsMessage.GuardMsg.Builder guardMsg = CaptureStrategicPointsMessage.GuardMsg.newBuilder();
                        guardMsg.setHeroId(fighterModule.get(i).getHeroId());
                        guardMsg.setStarlv(fighterModule.get(i).getStarlv());
                        guardMsg.setLevel(fighterModule.get(i).getLevel());
                        CustomsModuleBuilder.addHeros(guardMsg);
                    }
                    CustomsModuleBuilder.setPower(totalPower);
                    builder.addCustoms(CustomsModuleBuilder);
                }
            }

            //todo 4.最大通关关数
            HashMap<Integer, Integer> hashMap = module.getCheckpointRecord();
            int maxPassNum = hashMap.get(day) == null ? 0 : hashMap.get(day);
            builder.setMaxPassNum(maxPassNum);

            //todo 5.宝箱信息(获取那天的所有宝箱id，动态奖励返回)
            for (clearancereward clearancereward : reward.values()) {
                if (clearancereward.getField() == day) {
                    CaptureStrategicPointsMessage.RightBox.Builder rightBox = CaptureStrategicPointsMessage.RightBox.newBuilder();
                    rightBox.setDataId(clearancereward.getId());
                    rightBox.setIsReward(value.get(clearancereward.getId()));
                    int[] num = ArraryMesh.getNum(clearancereward.getRewardnum(), clearancereward.getDifficulty(), degree, -1);
                    Collection<Currency> curs = Currency.create(clearancereward.getRewardtype(), clearancereward.getRewardid(), num);
                    Collection<PackageMessage.Item> items = new CurrencyHandle().packItems(curs);
                    rightBox.addAllItem(items);
                    builder.addReward(rightBox);
                }
            }
            list.add(builder);
        }

        return list;
    }


    /**
     * 怪物信息
     *
     * @param id
     * @return
     */
    public static ArrayList<FighterModule> getFighterModule(int id) {
        RMap<String, ArrayList<FighterModule>> rMap = RedisManager.getInstance().getConnection(RedisType.REDIS_DATA).client().getMap("INIT:captureStrategicPoints");
        JSONArray arrary = (JSONArray) JSONArray.toJSON(rMap.get(String.valueOf(id)));
        ArrayList<FighterModule> fighterModules = JSON.parseObject(arrary.toString(), new TypeReference<>() {
        });
        return fighterModules;
    }


    /**
     * 战斗主逻辑
     *
     * @param playerCode
     * @param module
     * @param day
     * @return
     */
    public void battleResponseExecute(String playerCode, CaptureStrategicPointsModule module, int day, CaptureStrategicPointsMessage.CaptureStrategicPointsChallengeResponse.Builder response) {
        ArrayList<BattleModule> battleList = new ArrayList<>();
        Map<String, clearancemonster> monster = getAllData(clearancemonster.class);//怪物表
        ArrayList<Integer> list = new ArrayList<>();//怪物表的id

        for (clearancemonster clearancemonster : monster.values()) {
            if (clearancemonster.getField() == day) {
                list.add(clearancemonster.getId());
            }
        }

        HashMap<Integer, Integer> checkpointRecord = module.getCheckpointRecord();
        ArrayList<Integer> starMap = module.getStarMap();

        Integer integer = checkpointRecord.get(day);
        int winNum = 0;                             //当前胜利次数
        int winMax = integer == null ? 0 : integer; //最大通关次数
        int teamId = 0;                             //当前的玩家队伍
        boolean isAllWin = false;
        for (int monsterId : list) {
            clearancemonster data = DataCenter.getData(monsterId, clearancemonster.class);//怪物表
            BattleModule battleModule = BattleModule.create(playerCode);
            battleModule.setType(BattleType.CAPTUREPOINTS);
            battleModule.setCode(code());
            battleList.add(battleModule);
            // 玩家的team
            TeamModule teamA = playerTeam(teamId, module);
            // 怪物的team
            TeamModule teamB = monsterTeam(monsterId, module, data);
            boolean isWin = battleHandle(battleModule, teamA, teamB);
            if (isWin) {
                winNum = winNum + 1;
                if (!starMap.contains(monsterId)) {
                    starMap.add(monsterId);
                    module.setTotalStars(module.getTotalStars() + data.getStars());
                }
            }
            teamId++;
        }

        if (winMax < winNum) {
            checkpointRecord.put(day, winNum);
        }

        module.set();
        isAllWin = winNum > 0 ? true : false;

        // 处理录像
        ArrayList<BattleRecord> recordList = new ArrayList<>();
        for (BattleModule battleModule : battleList) {
            if (battleModule.getRecord() == null) {
                continue;
            }
            BattleRecord battleRecord = battleModule.saveRecord(BattleRecord.randomCode(), 1);
            BattleMessage.BattleExecuteResponse.Builder builder = BattleMessage.BattleExecuteResponse.newBuilder();
            builder.setPlayback(new BattleHandle().playback(battleRecord));//
            response.addBattleResp(builder);// 录像
        }

        response.setWin(isAllWin);//胜利与否
    }

    /**
     * 怪物队伍
     *
     * @param monsterId
     * @param module
     * @return
     */
    private TeamModule monsterTeam(int monsterId, CaptureStrategicPointsModule module, clearancemonster data) {
        TeamModule team = new TeamModule();
        ArrayList<FighterModule> fighterModule = getFighterModule(monsterId);
        int degree = module.getDegree();//难度等级
        long totalPower = 0;//战力
        for (int i = 0; i < data.getHeroid().length; i++) {
            Position position = Position.forValue(i + 1);
            int heroid = data.getHeroid()[i];
            if (heroid == -1) continue;
            FighterModule fight = fighterModule.get(i);
            //根据等级提升怪物难度
            fight.setLevel(fight.getLevel() + degree * 5);
            fight.getProperty().addPropertyDataBasicDegree(degree, 10);
            totalPower += fight.getTotalPower() + fight.getTotalPower() * degree * 0.05;
            team.addfighter(position, fight);
        }

        // 神器
        WeaponModule weapon = WeaponModule.create(data.getWeapondataid(), data.getWeaponlv(), 0, 0, data.getWeaponskilllv());
        team.setWeapon(weapon);

        // 信息
        team.setName(data.getName());
        team.setHead(data.getHead());
        team.setPower(totalPower);
        return team;
    }

    /**
     * 玩家队伍
     *
     * @param teamId
     * @param module
     * @return
     */
    private TeamModule playerTeam(int teamId, CaptureStrategicPointsModule module) {
        ArrayList<Format> formats = module.getFormats();
        Format format = formats.get(teamId);
        //检查如果武将被吃掉或找不到，删掉
        TeamModule team = new BattleHandle().teamPlayer(module.getPlayerCode(), format);
        return team;
    }


    /**
     * 生成战斗结果
     *
     * @param battleModule
     * @param teamA
     * @param teamB
     * @return
     */
    private boolean battleHandle(BattleModule battleModule, TeamModule teamA, TeamModule teamB) {
        if (teamA == null) {
            return false;
        }
        battleModule.setTeamA(teamA);
        if (teamB == null) {
            return true;
        }
        battleModule.setTeamB(teamB);

        BattleHandle battleHandle = new BattleHandle();

        Team team_a = teamA.team(true);
        Team team_b = teamB.team(false);
        team_a.setTeam对手(team_b);
        team_b.setTeam对手(team_a);

        // 处理战斗
        battleHandle.battleExecute(battleModule, team_a, team_b, 20);

        boolean isWin = battleModule.getBattleResult().equals(BattleResult.LEFT_WIN);

        return isWin;
    }


    //内部类------------------------------------------------------------------------------------------------------------
    static private class FormatMessageEntry {
        private ArrayList<FormatMessage.Format> formats;
        private ArrayList<HeroMessage.HeroSimple> heros;
        private ArrayList<Long> formatPower;

        private FormatMessageEntry() {
            formats = new ArrayList<>();
            heros = new ArrayList<>();
            formatPower = new ArrayList<>();
        }

        private ArrayList<FormatMessage.Format> getFormats() {
            return formats;
        }

        private ArrayList<HeroMessage.HeroSimple> getHeros() {
            return heros;
        }

        public ArrayList<Long> getFormatPower() {
            return formatPower;
        }

        public void addFormat(FormatMessage.Format format) {
            formats.add(format);
        }

        private void addHero(String playerCode, LinkedList<HeroMessage.HeroSimple> list) {
            heros.addAll(list);
        }

    }

}
